package Network

import (
	"SQL/FSDB"
	"logs"
	"os"
	"regexp"
	"strconv"
)

//---------------------------------------------- 类型检查

// FSJudger Judger Type Created by Ficow Shen
type FSJudger struct {
	argDict map[string]interface{}
}

func initJudger(args interface{}) (ok bool, errCode int, errMsg string, judger FSJudger) {
	if dict, ok := args.(map[string]interface{}); ok {
		judger = FSJudger{argDict: dict}
		return true, Success, "", judger
	}
	return false, errInvalidEmptyArgs, mInvalidEmptyArgs, FSJudger{}
}
func (j FSJudger) stringValueOf(key string) (val string, ok bool) {
	val, ok = j.argDict[key].(string)
	return
}
func (j FSJudger) boolValueOf(key string) (val bool, ok bool) {
	val, ok = j.argDict[key].(bool)
	return
}
func (j FSJudger) intValueOf(key string) (val int, ok bool) {
	val, ok = j.argDict[key].(int)
	return
}
func (j FSJudger) int64ValueOf(key string) (val int64, ok bool) {
	val, ok = j.argDict[key].(int64)
	return
}
func (j FSJudger) float64ValueOf(key string) (val float64, ok bool) {
	val, ok = j.argDict[key].(float64)
	return
}

//---------------------------------------------- 值检查

func checkPattern(pattern string, str string) (ok bool) {
	if ok, _ := regexp.MatchString(pattern, str); ok {
		return true
	}
	return false
}

func (j FSJudger) isValidID(IDKey string) (ok bool, errCode int, errMsg string, ID string) {

	if ID, ok = j.stringValueOf(IDKey); !ok {
		return false, errInvalidID, mInvalidUserID, ""
	}
	pattern := "^[0-9]{5,16}$"
	if checkPattern(pattern, ID) {
		switch IDKey {
		case "userID":
			ok, errCode, errMsg = isExistUserID(ID)
			return
		case "groupID":
			ok, errCode, errMsg = isExistGroupID(ID)
			return
		case "objectID":
			ok, errCode, errMsg = isExistObjectID(ID)
			return
		case "memberID":
			ok, errCode, errMsg = isExistMemberID(ID)
			return
		default:
			return true, Success, "", ID
		}
	}
	return false, errInvalidID, mInvalidUserID, ""
}

func (j FSJudger) isValidTime(timeKey string) (ok bool, errCode int, errMsg string, time string) {

	if time, ok = j.stringValueOf(timeKey); !ok {
		return false, errInvalidTime, mInvalidTime, ""
	}
	pattern := "^20[0-2][0-9]-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$"
	if checkPattern(pattern, time) {
		return true, Success, "", time
	}
	return false, errInvalidTime, mInvalidTime, ""
}
func (j FSJudger) isValidNickname() (ok bool, errCode int, errMsg string, nickname string) {

	if nickname, ok = j.stringValueOf("nickname"); !ok {
		return false, errInvalidNickname, mInvalidNickname, ""
	}
	l := len(nickname)
	if l > 0 && l < 40 {
		return true, Success, "", nickname
	}
	return false, errInvalidNickname, mInvalidNickname, ""
}
func (j FSJudger) isValidIconURL(iconKey string) (ok bool, errCode int, errMsg string, icon string) {

	if icon, ok = j.stringValueOf(iconKey); !ok {
		return false, errInvalidIcon, mInvalidIcon, ""
	}
	l := len(icon)
	if l > 0 && l < 50 {
		return true, Success, "", icon
	}
	return false, errInvalidIcon, mInvalidIcon, ""
}

func (j FSJudger) isValidPageIndex() (ok bool, errCode int, errMsg string, pIndex int) {

	var floatIndex float64
	if floatIndex, ok = j.float64ValueOf("pageIndex"); !ok {
		return false, errInvalidPageIndex, mInvalidPageIndex, -1
	}
	pIndex = int(floatIndex)
	if pIndex < 0 || pIndex > 999999 {
		return false, errInvalidPageSize, mInvalidPageIndex, -1
	}
	return true, Success, "", pIndex
}
func (j FSJudger) isValidPageSize() (ok bool, errCode int, errMsg string, pSize int) {

	var floatSize float64
	if floatSize, ok = j.float64ValueOf("pageSize"); !ok {
		return false, errInvalidPageSize, mInvalidPageSize, -1
	}
	pSize = int(floatSize)
	if pSize < 0 || pSize > 999 {
		return false, errInvalidPageSize, mInvalidPageSize, -1
	}
	return true, Success, "", pSize

}

func isValidMsgContent(msg string) (ok bool, errCode int, errMsg string) {

	l := len(msg)
	if l < 513 && l > 0 {
		return true, Success, ""
	}
	return false, errInvalidMsgContent, mInvalidMsgContent
}

//---------------------------------------------- HTTP参数检查

func isArgsEmptyInHTTP(args ...string) (ok bool, errCode int, errMsg string) {

	for _, arg := range args {
		if len(arg) == 0 {
			return true, errInvalidEmptyArgs, mInvalidEmptyArgs
		}
	}
	return false, Success, ""
}
func isValidTokenInHTTP(token string) (ok bool, errCode int, errMsg string) {

	pattern := "^[0-9a-zA-Z]{32}$"
	if checkPattern(pattern, token) {
		return true, Success, ""
	}
	return false, errInvalidTokenArg, mInvalidTokenArg
}
func isValidAccountInHTTP(account string) (ok bool, errCode int, errMsg string) {

	pattern := "^[0-9]{11}$"
	if checkPattern(pattern, account) {
		return true, Success, ""
	}
	return false, errInvalidID, mInvalidUserID
}
func isValidPwdInHTTP(pwd string) (ok bool, errCode int, errMsg string) {

	pattern := "^[\\da-zA-Z-_\\.\\?\\!\\,\\@\\#\\$\\%\\^\\&\\*\\(\\)\\=\\+\\[\\]\\{\\}]{6,20}$"
	if checkPattern(pattern, pwd) {
		return true, Success, ""
	}
	return false, errInvalidPassword, mInvalidPassword
}
func isValidBoolInHTTP(boolStr string) (ok bool, value bool, errCode int, errMsg string) {

	val, err := strconv.ParseBool(boolStr)
	if err != nil {
		return false, false, errInvalidBoolArg, mInvalidBoolArg
	}
	return true, val, Success, ""
}

func checkLogin(account string, pwd string) (errCode int, errMsg string, loginInfo LoginInfo) {

	loginSQL := `SELECT nickname,password,o.iconURL,o.id
				FROM users u,objects o 
				WHERE u.account=$1
						AND o.id = u.id`

	emptyInfo := LoginInfo{}
	rows, err := FSDB.Query(loginSQL, account)
	if err != nil {
		logs.Print("checkLogin 出错，err:", err.Error())
		return errDBQueryFailed, err.Error(), emptyInfo
	}
	defer rows.Close()

	if rows.Next() {
		var nickname string
		var password string
		var iconURL string
		var userID string
		err := rows.Scan(&nickname, &password, &iconURL, &userID)
		if err != nil {
			logs.Print("checkLoginInfo rows.Scan出错，err:", err.Error())
			return errDBQueryFailed, err.Error(), emptyInfo
		}
		if password == pwd {
			return Success, account + " 登录成功！", LoginInfo{nickname, iconURL, userID}
		}
	} else {
		return errAccountNotExist, "帐号不存在！", emptyInfo
	}
	return errPasswordWrong, "密码错误！", emptyInfo
}

//---------------------------------------------------is Exist

// // 增减群的时候，要对 fsValidGroupTable 进行更新
// var fsValidUserTable = map[string]bool{}
// var fsValidGroupTable = map[string]bool{}

// 如果返回的错误为nil,说明文件或文件夹存在
// 如果返回的错误类型使用os.IsNotExist()判断为true,说明文件或文件夹不存在
// 如果返回的错误为其它类型,则不确定是否在存在
func isPathOrFileExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
func isValidID(id string, idName string) (ok bool, errCode int, errMsg string) {

	pattern := "^[0-9]{5}$"
	if checkPattern(pattern, id) {
		switch idName {
		case "UserID":
			ok, errCode, errMsg = isExistUserID(id)
			return
		case "GroupID":
			ok, errCode, errMsg = isExistGroupID(id)
			return
		case "ObjectID":
			ok, errCode, errMsg = isExistObjectID(id)
			return
		case "MemberID":
			ok, errCode, errMsg = isExistMemberID(id)
			return
		default:
			return true, Success, ""
		}
	}
	return false, errInvalidID, mInvalidUserID
}

func isExistObjectID(id string) (ok bool, errCode int, errMsg string) {

	// if _, isExist := fsValidUserTable[id]; isExist {
	// 	return true, Success, ""
	// }
	// if _, isExist := fsValidGroupTable[id]; isExist {
	// 	return true, Success, ""
	// }
	sql := `SELECT id 
			FROM objects 
			WHERE id = $1`
	rows, err := FSDB.Query(sql, id)
	if err != nil {
		logs.Print("isIDExist Query 出错，err:", err.Error())
		return false, errDBQueryFailed, err.Error()
	}
	defer rows.Close()

	if rows.Next() {
		var id string
		err := rows.Scan(&id)
		if err != nil {
			logs.Print("isIDExist rows.Scan出错，err:", err.Error())
			return false, errDBQueryFailed, err.Error()
		}
	} else {
		return false, errNotExistID, mNotExistObjectID
	}
	return true, Success, ""
}
func isExistUserID(id string) (ok bool, errCode int, errMsg string) {

	// if _, isExist := fsValidUserTable[id]; isExist {
	// 	return true, Success, ""
	// }
	sql := `SELECT id 
			FROM users 
			WHERE id = $1`
	rows, err := FSDB.Query(sql, id)
	if err != nil {
		logs.Print("isIDExist Query 出错，err:", err.Error())
		return false, errDBQueryFailed, err.Error()
	}
	defer rows.Close()

	if rows.Next() {
		var id string
		err := rows.Scan(&id)
		if err != nil {
			logs.Print("isIDExist rows.Scan出错，err:", err.Error())
			return false, errDBQueryFailed, err.Error()
		}
	} else {
		return false, errNotExistID, mNotExistUserID
	}
	// fsValidUserTable[id] = true
	return true, Success, ""
}
func isExistMangagerID(managerID string) (ok bool, errCode int, errMsg string) {

	// TODO: FICOW 管理员要验证群！
	if ok, errCode, errMsg = isValidID(managerID, "UserID"); !ok {
		return
	}
	sql := `SELECT id 
			FROM users 
			WHERE id = $1 AND ismanager=true`
	rows, err := FSDB.Query(sql, managerID)
	if err != nil {
		logs.Print("isIDExist Query 出错，err:", err.Error())
		return false, errDBQueryFailed, err.Error()
	}
	defer rows.Close()

	if rows.Next() {
		var id string
		err := rows.Scan(&id)
		if err != nil {
			logs.Print("isIDExist rows.Scan出错，err:", err.Error())
			return false, errDBQueryFailed, err.Error()
		}
	} else {
		return false, errInvalidManager, mInvalidManager
	}
	// fsValidUserTable[id] = true
	return true, Success, ""
}
func isExistTalkerID(userID string, talkerID string, talkerIsUser bool) (ok bool, errCode int, errMsg string) {

	if !talkerIsUser {
		ok, errCode, errMsg = isExistGroupID(talkerID)
		if errCode != Success {
			return
		}
		ok, errCode, errMsg = isExistUserInGroup(userID, talkerID)
		return
	}
	ok, errCode, errMsg = isExistUserID(talkerID)
	if errCode == errNotExistID {
		errMsg = mNotExistTalkerID
	}
	return
}
func isExistMemberID(id string) (ok bool, errCode int, errMsg string) {
	ok, errCode, errMsg = isExistUserID(id)
	if errCode == errNotExistID {
		errMsg = mNotExistMemberID
	}
	return
}
func isExistGroupID(id string) (ok bool, errCode int, errMsg string) {

	// if _, isExist := fsValidGroupTable[id]; isExist {
	// 	return true, Success, ""
	// }
	sql := `SELECT id 
			FROM groups 
			WHERE id = $1`
	rows, err := FSDB.Query(sql, id)
	if err != nil {
		logs.Print("isIDExist Query 出错，err:", err.Error())
		return false, errDBQueryFailed, err.Error()
	}
	defer rows.Close()

	if rows.Next() {
		var id string
		err := rows.Scan(&id)
		if err != nil {
			logs.Print("isIDExist rows.Scan出错，err:", err.Error())
			return false, errDBQueryFailed, err.Error()
		}
	} else {
		return false, errNotExistID, mNotExistGroupID
	}
	// fsValidGroupTable[id] = true
	return true, Success, ""
}
func isExistUserInGroup(userID string, groupID string) (ok bool, errCode int, errMsg string) {

	sql := `SELECT userid 
			FROM members
			WHERE userid = $1 AND groupid = $2`
	rows, err := FSDB.Query(sql, userID, groupID)
	if err != nil {
		logs.Print("isIDExist Query 出错，err:", err.Error())
		return false, errDBQueryFailed, err.Error()
	}
	defer rows.Close()

	if rows.Next() {
		var id string
		err := rows.Scan(&id)
		if err != nil {
			logs.Print("isIDExist rows.Scan出错，err:", err.Error())
			return false, errDBQueryFailed, err.Error()
		}
	} else {
		return false, errNotExistUserInGroup, mNotExistUserInGroup
	}
	return true, Success, ""
}
